package com.sunwayworld.basemodule.business.batch.service.impl;

import com.sunwayworld.basemodule.business.batch.bean.LimsBatchSampleProductBean;
import com.sunwayworld.basemodule.business.batch.dao.LimsBatchSampleProductDao;
import com.sunwayworld.basemodule.business.batch.service.LimsBatchSampleProductService;
import com.sunwayworld.basemodule.business.folder.bean.LimsFolderBean;
import com.sunwayworld.basemodule.business.folder.service.LimsFolderService;
import com.sunwayworld.basemodule.business.ordertask.bean.LimsOrderTaskBean;
import com.sunwayworld.basemodule.business.ordertask.service.LimsOrderTaskService;
import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.data.page.Page;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Repository
@GikamBean
public class LimsBatchSampleProductServiceImpl implements LimsBatchSampleProductService {

    @Autowired
    private LimsBatchSampleProductDao limsBatchSampleProductDao;

    @Override
    @SuppressWarnings("unchecked")
    public LimsBatchSampleProductDao getDao() {
        return limsBatchSampleProductDao;
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        LimsBatchSampleProductBean limsBatchSampleProduct = jsonWrapper.parseUnique(LimsBatchSampleProductBean.class);
        limsBatchSampleProduct.setId(ApplicationContextHelper.getNextIdentity());
        getDao().insert(limsBatchSampleProduct);
        return limsBatchSampleProduct.getId();
    }

    @Override
    public Page<LimsBatchSampleProductBean> selectBatchSampleProducts(RestJsonWrapperBean wrapperBean) {
        return selectPagination(() -> getDao().selectBatchSampleProducts(wrapperBean.extractMapFilter()), wrapperBean.extractPageRowBounds());
    }

    //    @Async
    @Transactional
    @Override
    public void setBatchProductStatus(List<Long> fromIds) {
        LimsFolderService folderService = ApplicationContextHelper.getBean(LimsFolderService.class);
        LimsOrderTaskService orderTaskService = ApplicationContextHelper.getBean(LimsOrderTaskService.class);
        List<LimsFolderBean> from = folderService.selectListByIds(fromIds);
        if (from.isEmpty()) {
            return;
        }
        List<LimsBatchSampleProductBean> batchProductSelectBy = new ArrayList<>();
        List<LimsFolderBean> folderBeanSearchBy = new ArrayList<>();
        from.forEach(f -> {
            LimsBatchSampleProductBean bean = new LimsBatchSampleProductBean();
            bean.setProductCode(f.getProductCode());// 质控样得项目没有productid，只能通过code
            bean.setBatchSampleId(f.getBatchSampleId());
            batchProductSelectBy.add(bean);

            LimsFolderBean folderBean = new LimsFolderBean();
            folderBean.setProductCode(f.getProductCode());// 质控样得项目没有productid，只能通过code
            folderBean.setBatchSampleId(f.getBatchSampleId());
            folderBeanSearchBy.add(folderBean);
        });
        if (!batchProductSelectBy.isEmpty()) {
            List<LimsBatchSampleProductBean> batchProductUpdateBy = this.getDao().selectList(batchProductSelectBy, Arrays.asList("batchSampleId", "productCode"), Arrays.asList("id", "batchSampleId", "productCode"));
            List<LimsFolderBean> folderBeans = folderService.getDao().selectList(folderBeanSearchBy, Arrays.asList("batchSampleId", "productCode"), Arrays.asList("id", "batchSampleId", "productCode"));
            List<Long> folderIds = folderBeans.stream().map(LimsFolderBean::getId).collect(Collectors.toList());
            List<LimsOrderTaskBean> odTasks = orderTaskService.getDao().selectListByOneColumnValues(folderIds, "folderId", Arrays.asList("Id", "folderId", "status"));

            batchProductUpdateBy.forEach(bp -> {
                List<Long> tempFolderIds = folderBeans.stream().filter(f -> f.getProductCode().equals(bp.getProductCode()) && f.getBatchSampleId().equals(bp.getBatchSampleId())).map(LimsFolderBean::getId).collect(Collectors.toList());
                AtomicInteger doneNum = new AtomicInteger(0);
                AtomicInteger abnormalNum = new AtomicInteger(0);
                AtomicInteger stopNum = new AtomicInteger(0);
                AtomicInteger doingNum = new AtomicInteger(0);
                odTasks.stream().filter(ot -> tempFolderIds.contains(ot.getFolderId())).forEach(ot -> {
                    switch (ot.getStatus()) {
                        case "done": {
                            doneNum.getAndIncrement();
                        }
                        break;
                        case "draft":
                        case "logged":
                        case "approve": {
                            doingNum.getAndIncrement();
                        }
                        break;
                        case "abnormal": {
                            abnormalNum.getAndIncrement();
                        }
                        break;
                        case "stop": {
                            stopNum.getAndIncrement();
                        }
                        break;
                    }
                });
                if (abnormalNum.get() > 0) {
                    bp.setStatus("expAbnormal");
                    return;
                }
                if (doingNum.get() > 0) {
                    bp.setStatus("inExperiment");
                    return;
                }
//                if (abnormalNum.get() == 0 && doingNum.get() == 0) {
                // ordtask没有在进行中的任务（ordtask状态全部为stop或者done）
                bp.setStatus("expDone");
                return;
//                }


/*                bp.setStatus("inExperiment");
                // 如果终止和异常数都为0
                if (stopNum.get() == 0 && abnormalNum.get() == 0) {
                    if (doingNum.get() == 0) {
                        // 全都结束
                        bp.setStatus("expDone");
                        return;
                    } else {
                        // 正在进行的任务不为0
                        bp.setStatus("inExperiment");
                        return;
                    }
                }
                if (abnormalNum.get() > 0) {
                    bp.setStatus("expAbnormal");
                    return;
                }
                // 终止任务不为0，且没有正在进行的任务、异常的任务
                if (stopNum.get() > 0 && doingNum.get() == 0 && abnormalNum.get() == 0) {
                    bp.setStatus("expStop");
                    return;
                }*/
            });
            if (!batchProductUpdateBy.isEmpty()) {
                this.getDao().fastUpdate(batchProductUpdateBy, "status");
            }
        }
    }

    //    @Async
    @Transactional
    @Override
    public void setBatchProductWithStatus(List<Long> folderIds, String newStatus) {
        LimsFolderService folderService = ApplicationContextHelper.getBean(LimsFolderService.class);
        List<LimsFolderBean> folderBeans = folderService.selectListByIds(folderIds);
        if (folderBeans.isEmpty()) {
            return;
        }
        List<LimsBatchSampleProductBean> batchProductSelectBy = new ArrayList<>();
        folderBeans.forEach(f -> {
            LimsBatchSampleProductBean bean = new LimsBatchSampleProductBean();
            bean.setProductCode(f.getProductCode());// 质控样得项目没有productid，只能通过code
            bean.setBatchSampleId(f.getBatchSampleId());
            batchProductSelectBy.add(bean);
        });
        if (!batchProductSelectBy.isEmpty()) {
            List<LimsBatchSampleProductBean> batchProductUpdateBy = this.getDao().selectList(batchProductSelectBy, Arrays.asList("batchSampleId", "productCode"), Collections.singletonList("id"));
            List<Long> bspIds = batchProductUpdateBy.stream().map(LimsBatchSampleProductBean::getId).collect(Collectors.toList());
            if (!bspIds.isEmpty()) {
                LimsBatchSampleProductBean updateBy = new LimsBatchSampleProductBean();
                updateBy.setStatus(newStatus);
                this.getDao().updateByIds(updateBy, bspIds, "status");
            }
        }
    }
}
